import os
import time
import datetime
import traceback
from threading import Thread

import pandas as pd
from mootdx.quotes import Quotes

from tools.utils_basic import pd_show_all
from tools.utils_cache import check_is_open_day, load_json, save_json
from z_tdx.lc5_mootdx import write_df_to_lc


TARGET_LC_FOLDER = './_cache/debug'         # 写入路径

SYMBOL_SOURCE_SZ = './_cache/stock_sz.txt'  # 股票列表文件
SYMBOL_TARGET_SZ = '/sz'                    # 写入文件夹名

SYMBOL_SOURCE_SH = './_cache/stock_sh.txt'  # 股票列表文件
SYMBOL_TARGET_SH = '/sh'                    # 写入文件夹名

STOCK_GROUP_SIZE = 10                       # 每组股票数量
KLINES_FREQUENCY = '5m'                     # 取值5m, 30m 或者 days

UPDATE_TASK_INTERVAL = 1                    # 每隔几秒执行一次
LOCAL_CACHE_DATETIME = './_cache/_cache_datetime.json'


client = Quotes.factory(market='std', multithread=False, heartbeat=False)
cache_datetime = {}     # 记录最近一次的时间
path_of_symbol = {}     # code: path


def write(df: pd.DataFrame, symbol: str, symbol_file: str):
    if len(df) > 0:
        dt = df['datetime'].values[-1]
        # 记录不同的时候写
        if symbol in cache_datetime:
            if cache_datetime[symbol] != dt:
                cache_datetime[symbol] = dt  # 确保只写一次
                write_df_to_lc(df, f'{path_of_symbol[symbol]}/{symbol_file}.lc5')
        # 没有记录的时候写
        else:
            cache_datetime[symbol] = dt
            write_df_to_lc(df, f'{path_of_symbol[symbol]}/{symbol_file}.lc5')


def run(now_min: str):
    for symbol in path_of_symbol:
        print(symbol)
        if symbol[:2] in ['00', '30']:
            symbol_file = 'sz' + symbol
        elif symbol[:2] in ['60', '68']:
            symbol_file = 'sh' + symbol
        else:
            symbol_file = 'bj' + symbol

        try:
            df = client.bars(symbol=symbol, frequency=KLINES_FREQUENCY, offset=2, adjust='qfq')
            if len(df) > 1:
                if '11:31' <= now_min <= '11:40' or '15:01' <= now_min <= '15:10':
                    df = df.tail(1)     # 倒数第一个
                else:
                    df = df.iloc[:-1]   # 倒数第二个

                    # 如果前一个时间是 15 就不写了
                    dt = df['datetime'].values[-1]
                    if datetime.datetime.strptime(dt, '%Y-%m-%d %H:%M').hour == 15:
                        continue
                write(df, symbol, symbol_file)
            elif len(df) == 1:
                df = df.tail(1)         # 只有一行那就第一个
                write(df, symbol, symbol_file)
        except Exception as e:
            print(symbol, '出错！', e)
            traceback.print_exc()

    # 每次 run 完 save 一下 cache
    save_json(LOCAL_CACHE_DATETIME, cache_datetime)


def schedule():
    while True:
        now = datetime.datetime.now()
        now_day = now.strftime('%Y-%m-%d')
        now_min = now.strftime("%H:%M")
        now_sec = now.strftime("%S")
        print_beat(now_min)

        if check_is_open_day(now_day):
            if '09:30' <= now_min <= '11:35' or '13:00' <= now_min <= '15:05':
                if int(now_sec) % UPDATE_TASK_INTERVAL == 0:
                    run(now_min)

        sec = datetime.datetime.now().second
        time.sleep(60 - sec)


def print_beat(now_min: str):
    if int(now_min[-2:]) % 60 == 0:
        print(f'\n[{now_min}]', end='')  # 每小时一行新数据print
    if int(now_min[-2:]) % 10 == 9:
        print('x', end='')
    else:
        print('.', end='')


def prepare_folders(source_path: str, target_path: str, folder_number_start: int):
    def set_path():
        folder = f'{TARGET_LC_FOLDER}{j}'
        if not os.path.exists(folder):
            os.mkdir(folder)

        path = f'{TARGET_LC_FOLDER}{j}{target_path}'
        if not os.path.exists(path):
            os.mkdir(path)
        for symbol in symbols:
            path_of_symbol[symbol] = path

    i = 0
    j = folder_number_start
    is_set = False
    with open(source_path, 'r') as r:
        line = r.readline()
        symbols = []
        while line:
            if len(line) > 0:
                symbols.append(str.strip(line))
                i += 1
                if i == STOCK_GROUP_SIZE:
                    set_path()
                    is_set = True
                    i = 0
                    j += 1
                    symbols = []
            line = r.readline()
    if i > 0:
        set_path()
    if not is_set:
        j -= 1
    return j


def main():
    global cache_datetime
    try:
        cache_datetime = load_json(LOCAL_CACHE_DATETIME)
        print("定时器已启动！")
        time.sleep(60 - datetime.datetime.now().second)  # 保证每分钟开始一秒执行
        Thread(target=schedule).start()
    except KeyboardInterrupt:
        save_json(LOCAL_CACHE_DATETIME, cache_datetime)
        print("手动停止任务调度。")


def test():
    pd_show_all()
    run('11:31')


if __name__ == '__main__':
    from warnings import simplefilter
    simplefilter(action='ignore', category=FutureWarning)

    folder_index = prepare_folders(SYMBOL_SOURCE_SZ, SYMBOL_TARGET_SZ, 1)
    prepare_folders(SYMBOL_SOURCE_SH, SYMBOL_TARGET_SH, folder_index + 1)

    main()

    # i = 0
    # for k in path_of_symbol:
    #     i += 1
    #     print(i, k, path_of_symbol[k])
    # test()
